#pragma once 

#include "Window.h"
#include "MessageMap.h"
#include "Utility.h"

namespace My {

template <class T>
class CustomWindow : public Window<T>
{
public:
	CustomWindow();
protected:
	CBitmap			m_OffBmp;
	CBitmap *		m_pDefBmp;
	CDC				m_OffDC;
	CSize			m_OffSize;
public:
	CDC * GetOffDC()
		{ return &m_OffDC; }
public:
	virtual void UpdateBounds();
	virtual void UpdateOffscreenDC(int cx = 0, int cy = 0);
protected:
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnDestroy();
	afx_msg void OnPaint();
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);

	DECLARE_MESSAGE_MAP()
};

#if (_MFC_VER < 0x0800)

BEGIN_MESSAGE_MAP_TEMPLATE2(CustomWindow, Window)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_PAINT()
	ON_WM_SIZE()
	ON_WM_ACTIVATE()
END_MESSAGE_MAP()

#else

BEGIN_TEMPLATE_MESSAGE_MAP(CustomWindow, T, Window<T>)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_PAINT()
	ON_WM_SIZE()
	ON_WM_ACTIVATE()
END_MESSAGE_MAP()

#endif

template <class T>
CustomWindow<T>::CustomWindow()
{ 
	m_pDefBmp = 0; 
}

template <class T>
void CustomWindow<T>::UpdateBounds()
{
	CRect r = Bounds();
	if (m_hWnd != 0) {
		Control * pParent = My::Control::Parent();
		if (pParent != 0)
			r.OffsetRect(pParent->GetWindowOffset());
		CWnd::SetWindowPos(0, r.left, r.top, r.Width(), r.Height(), NULL);
	}
}

template <class T>
void CustomWindow<T>::UpdateOffscreenDC(int cx, int cy)
{
	CSize s = m_OffSize;
	if (cx > s.cx)
		s.cx = cx;
	if (cy > s.cy)
		s.cy = cy;

	if (m_OffSize != s && m_OffDC.m_hDC != 0)
	{
		ClientDC dc(this);

		m_OffSize = s;
		m_OffDC.SelectObject(m_pDefBmp);
		m_OffBmp.DeleteObject();
		m_OffBmp.CreateCompatibleBitmap(&dc, m_OffSize.cx, m_OffSize.cy);
		m_pDefBmp = m_OffDC.SelectObject(&m_OffBmp);
	}
}

template <class T>
int CustomWindow<T>::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (Window<T>::OnCreate(lpCreateStruct) == -1)
		return -1;

	assert(m_hWnd != 0);

	m_OffSize = CSize(1, 1);

	ClientDC dc(this);

	m_OffBmp.CreateCompatibleBitmap(&dc, 1, 1);
	m_OffDC.CreateCompatibleDC(&dc);
	m_pDefBmp = m_OffDC.SelectObject(&m_OffBmp);	

	return 0;
}

template <class T>
void CustomWindow<T>::OnDestroy()
{
	Window<T>::OnDestroy();
}

template <class T>
void CustomWindow<T>::OnPaint() 
{
	CRect r;
	GetUpdateRect(&r);
	CPaintDC dc(this);
	Paint(&m_OffDC, r);
	dc.BitBlt(r.left, r.top, r.Width(), r.Height(), &m_OffDC, r.left, r.top, SRCCOPY);
}

template <class T>
void CustomWindow<T>::OnSize(UINT nType, int cx, int cy) 
{	
	T::OnSize(nType, cx, cy);	
	UpdateOffscreenDC(cx, cy);
	Container::UpdateBounds();
}


template <class T>
void CustomWindow<T>::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
{
	T::OnActivate(nState, pWndOther, bMinimized);
	ProcessEvent(ActivateEvent(nState != WA_INACTIVE));
}

} // My
